﻿Imports System.IO
Imports System.Linq
Imports System.Text

Namespace CustomClasses.IO
    Public Class EndianAwareBinaryReader
        Inherits BinaryReader
        Private mIsLittleEndian As Boolean
        Private buffer As Byte() = New Byte(7) {}

        Public Sub New(input As Stream, encoding As Encoding, isLittleEndian As Boolean)
            MyBase.New(input, encoding)
            Me.mIsLittleEndian = isLittleEndian
        End Sub

        Public Sub New(input As Stream, isLittleEndian As Boolean)
            Me.New(input, Encoding.UTF8, isLittleEndian)
        End Sub

        Public Property IsLittleEndian() As Boolean
            Get
                Return mIsLittleEndian
            End Get
            Set(value As Boolean)
                mIsLittleEndian = value
            End Set
        End Property


        Public Overrides Function ReadDouble() As Double
            If mIsLittleEndian Then
                Return MyBase.ReadDouble()
            End If
            FillMyBuffer(8)
            Return BitConverter.ToDouble(buffer.Take(8).Reverse().ToArray(), 0)
        End Function

        Public Overrides Function ReadInt16() As Short
            If mIsLittleEndian Then
                Return MyBase.ReadInt16()
            End If
            FillMyBuffer(2)
            Return BitConverter.ToInt16(buffer.Take(2).Reverse().ToArray(), 0)

        End Function

        Public Overrides Function ReadInt32() As Integer
            If mIsLittleEndian Then
                Return MyBase.ReadInt32()
            End If
            FillMyBuffer(4)
            Return BitConverter.ToInt32(buffer.Take(4).Reverse().ToArray(), 0)

        End Function

        Public Overrides Function ReadInt64() As Long
            If mIsLittleEndian Then
                Return MyBase.ReadInt64()
            End If
            FillMyBuffer(8)
            Return BitConverter.ToInt64(buffer.Take(8).Reverse().ToArray(), 0)

        End Function

        Public Overrides Function ReadSingle() As Single
            If mIsLittleEndian Then
                Return MyBase.ReadSingle()
            End If
            FillMyBuffer(4)
            Return BitConverter.ToSingle(buffer.Take(4).Reverse().ToArray(), 0)
        End Function

        Public Overrides Function ReadUInt16() As UShort
            If mIsLittleEndian Then
                Return MyBase.ReadUInt16()
            End If
            FillMyBuffer(2)
            Return BitConverter.ToUInt16(buffer.Take(2).Reverse().ToArray(), 0)
        End Function


        Public Overrides Function ReadUInt32() As UInteger
            If mIsLittleEndian Then
                Return MyBase.ReadUInt32()
            End If
            FillMyBuffer(4)
            Return BitConverter.ToUInt32(buffer.Take(4).Reverse().ToArray(), 0)
        End Function

        Public Overrides Function ReadUInt64() As ULong
            If mIsLittleEndian Then
                Return MyBase.ReadUInt64()
            End If
            FillMyBuffer(8)
            Return BitConverter.ToUInt64(buffer.Take(8).Reverse().ToArray(), 0)
        End Function

        Private Sub FillMyBuffer(numBytes As Integer)
            Dim offset As Integer = 0
            Dim num2 As Integer = 0
            If numBytes = 1 Then
                num2 = BaseStream.ReadByte()
                If num2 = -1 Then
                    Throw New EndOfStreamException("Attempted to read past the end of the stream.")
                End If
                buffer(0) = CByte(num2)
            Else
                Do
                    num2 = BaseStream.Read(buffer, offset, numBytes - offset)
                    If num2 = 0 Then
                        Throw New EndOfStreamException("Attempted to read past the end of the stream.")
                    End If
                    offset += num2
                Loop While offset < numBytes
            End If
        End Sub
    End Class
End Namespace
